﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AdventureWorks.Entities;
using AdventureWorksData.DAO;
using AdventureWorks.Helpers;
using AdventureWorks.Exceptions;

namespace AdventureWorks.Business
{
	public class ProductModelBusiness : IBusiness<ProductModel>, IDisposable
	{
		private readonly IUnitOfWork _db;
		private IEnumerable<ProductModel> _models;

		public ProductModelBusiness()
		{
			_db = new UnitOfWork();
		}

		public ProductModelBusiness(IUnitOfWork entityDb)
		{
			_db = entityDb;
		}

		public ProductModel Get(int id)
		{
			var model = _db.ProductModels.Get(i => i.ID == id, includeProperties: "Products").First();
			return model;
		}

		public IEnumerable<ProductModel> GetList(String sortOrder, String searchString)
		{
			_models = _db.ProductModels.Get();
			FilterWithSearchString(searchString);
			SortOrder(sortOrder);

			return _models;
		}

		private void FilterWithSearchString(string searchString)
		{
			if (!String.IsNullOrEmpty(searchString))
			{
				_models = _models.Where(p =>
					CustomComparer.CompareString(
						new String[] { p.ID.ToString(), p.Name, p.CatalogDescription },
						searchString));
			}
		}

		private void SortOrder(string sortOrder)
		{
			switch (sortOrder)
			{
				case "Name Desc":
					_models = _models.OrderByDescending(p => p.Name);
					break;
				case "ID":
					_models = _models.OrderBy(p => p.ID);
					break;
				case "ID Desc":
					_models = _models.OrderByDescending(p => p.ID);
					break;
				case "Modified":
					_models = _models.OrderBy(p => p.ModifiedDate);
					break;
				case "Modified Desc":
					_models = _models.OrderByDescending(p => p.ModifiedDate);
					break;
				default:
					_models = _models.OrderBy(p => p.Name);
					break;
			}
		}

		public void Insert(ProductModel entity)
		{
			if (entity.Validate())
			{
				_db.ProductModels.Insert(entity);
			}
			else
			{
				ThrowInvalidException();
			}
		}

		public void Update(ProductModel entity)
		{
			entity.ModifiedDate = DateTime.Now;
			if (entity.Validate())
			{
				_db.ProductModels.Update(entity);
			}
			else
			{
				ThrowInvalidException();
			}
		}

		public void Delete(int id)
		{
			var model = _db.ProductModels.Get(m => m.ID == id, includeProperties: "Products").First();

			if (model.Products.Count > 0)
			{
				throw new BusinessException(ExceptionMessages.ModelWithProducts);
			}

			_db.ProductModels.Delete(id);
		}

		public void Save()
		{
			_db.Save();
		}

		public void Dispose()
		{
			_db.Dispose();
		}


		public void ThrowInvalidException()
		{
			throw new BusinessException("Invalid Product Model");
		}
	}
}
